package com.xmler.plugin.adbrocket.ui;

import com.android.ddmlib.IDevice;
import com.android.ddmlib.MultiLineReceiver;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.wm.ToolWindow;
import com.xmler.plugin.adbrocket.adb.AdbFacade;
import com.xmler.plugin.adbrocket.adb.DeviceResult;
import com.xmler.plugin.adbrocket.adb.DeviceResultList;
import com.xmler.plugin.adbrocket.adb.command.InputAnyCmd;
import com.xmler.plugin.adbrocket.bean.ComboDeviceBean;
import com.xmler.plugin.adbrocket.bean.ProcessBean;
import com.xmler.plugin.adbrocket.shell.ShellFacade;
import com.xmler.plugin.adbrocket.ui.renderer.DeviceComboBoxRenderer;
import com.xmler.plugin.adbrocket.ui.renderer.ProcessComboBoxRenderer;
import com.xmler.plugin.adbrocket.utils.AdbUtil;
import com.xmler.plugin.adbrocket.utils.Logger;

import javax.swing.*;
import java.awt.event.ItemEvent;
import java.util.List;
import java.util.function.Function;

public class AdbRocketWindow {
    private JComboBox cb_devices;
    private JComboBox cb_apps;
    private JButton btn_refresh;
    private JLabel label_screen;
    private JLabel label_os;
    private JLabel label_abilist;
    private JButton btn_adb_restart;
    private JButton btn_app_uninstall;
    private JButton btn_app_kill;
    private JButton btn_app_start;
    private JButton btn_app_restart;
    private JButton btn_cnt_wifi;
    private JTextArea text_area_log;
    private JTextField text_input_cmd;
    private JPanel panel_content;
    private JButton btn_cnt_usb_wifi;
    private JPanel device_info;
    private JLabel label_ip_wlan;
    private JButton btn_clr;
    private JButton btn_clr_restart;
    private JPanel clear_data;
    private JButton btn_input_send;

    private final Project project;
    private DeviceResultList deviceResultList;

    private WindowDisplayReceiver mWindowDisplayReceiver;

    public AdbRocketWindow(Project project, ToolWindow toolWindow) {
        this.project = project;
        Logger.addInterceptor(message -> {
            text_area_log.append(message + "\n");
        });

        beautyComponents();
//         ==========================================================================================
//        https://docs.oracle.com/javase/tutorial/uiswing/lookandfeel/synth.html
//        try {
//            SynthLookAndFeel lookAndFeel = new SynthLookAndFeel();
//            lookAndFeel.load(AdbRocketWindow.class.getResourceAsStream("/ui-style.xml"), AdbRocketWindow.class);
//            UIManager.setLookAndFeel(lookAndFeel);
//        } catch (ParseException e) {
//            e.printStackTrace();
//        } catch (UnsupportedLookAndFeelException e) {
//            e.printStackTrace();
//        }
//         ==========================================================================================

        refresh();

        bindListener(project);
    }

    private void beautyComponents() {
        cb_apps.setRenderer(new ProcessComboBoxRenderer());
    }

    public JPanel getContentRoot(){
        return panel_content;
    }

    private void bindListener(Project project) {
        btn_refresh.addActionListener(e -> {
            refresh();

        });
        cb_devices.addItemListener((e) -> {
            if (e.getStateChange() == ItemEvent.SELECTED) {
                obtainDeviceInfo(getCurrent());
            }
        });
        btn_adb_restart.addActionListener(e -> {
            Logger.d("adb restart-server clicked... waiting");
            ShellFacade.INSTANCE.restartAdbServer(project);
        });
        btn_app_uninstall.addActionListener(e -> {
            Logger.d("uninstall app clicked... waiting");
            AdbFacade.INSTANCE.appUninstall(project,
                    getCurrent());
        });
        btn_app_kill.addActionListener(e -> {
            Logger.d("kill app clicked... waiting");
            AdbFacade.INSTANCE.appKill(project, getCurrent());
        });

        btn_app_start.addActionListener(e -> {
            Logger.d("start app clicked... waiting");
            AdbFacade.INSTANCE.appStart(project, getCurrent());
        });

        btn_app_restart.addActionListener(e -> {
            Logger.d("re-start app clicked... waiting");
            AdbFacade.INSTANCE.appRestart(project, getCurrent());
        });

        btn_clr.addActionListener(e -> {
            Logger.d("clear data clicked... waiting");
            AdbFacade.INSTANCE.clearData(project, getCurrent());
        });

        btn_clr_restart.addActionListener(e -> {
            Logger.d("clear data & restart app clicked... waiting");
            AdbFacade.INSTANCE.clearDataAndRestartActivity(project, getCurrent());
        });

        btn_cnt_usb_wifi.addActionListener(e -> {
            Logger.d("usb to wifi clicked... waiting");
            AdbFacade.INSTANCE.usbToWifiConnect(project, getCurrent());
        });

        btn_input_send.addActionListener(e -> {
            Logger.d("send input text clicked... waiting");
            final String text = text_input_cmd.getText().trim();
            if (text == null || text.length() == 0) {
                Logger.d("Please input text");
                return;
            }
            AdbFacade.INSTANCE.keyboradInput(project, getCurrent(), text);
        });
    }

    private void refresh(){
        cb_devices.removeAllItems();
        cb_apps.removeAllItems();

        cb_devices.setRenderer(new DeviceComboBoxRenderer());
        deviceResultList = AdbFacade.INSTANCE.fetchDevices(project);
        List<IDevice> devices = deviceResultList.getDevices();
        devices.stream().map(new Function<IDevice, ComboDeviceBean>() {
            @Override
            public ComboDeviceBean apply(IDevice iDevice) {
                return new ComboDeviceBean(iDevice);
            }
        }).forEach(item -> {
            cb_devices.addItem(item);
        });


        List<ProcessBean> processBeanList  = ShellFacade.INSTANCE
                .queryAllDebugableProcesses(project, devices.size() > 0 ? devices.get(0) : null);

        if (processBeanList.isEmpty()) {
            cb_apps.addItem(new ProcessBean(-1, "No debuggable processes"));
        }else {
            for (int i = 0; i < processBeanList.size(); i++) {
                cb_apps.addItem(processBeanList.get(i));
            }
        }

        obtainDeviceInfo(getCurrent());
    }
    private DeviceResult getCurrent() {
        int d = cb_devices.getSelectedIndex();
        int f = cb_apps.getSelectedIndex();
        if (d < 0 || f < 0) {
            return null;
        }
        return new DeviceResult(deviceResultList.getDevices().get(d),
                deviceResultList.getFacet().get(f),
                ((ProcessBean)cb_apps.getSelectedItem()).getPackageName(),
                text_area_log);
    }

    private void resetDeviceInfo(){
        label_screen.setText("");
        label_abilist.setText("");
        label_os.setText("");
    }

    private void obtainDeviceInfo(DeviceResult deviceResult) {
        resetDeviceInfo();
        if (deviceResult == null) {
            return;
        }
        final IDevice device = deviceResult.getDevice();
        if (!device.isOnline())return;

        final int densityDpi = device.getDensity();
        if (mWindowDisplayReceiver == null) {
            mWindowDisplayReceiver = new WindowDisplayReceiver(densityDpi);
        }
        AdbFacade.INSTANCE.executeShell(this.project, deviceResult, new InputAnyCmd("dumpsys window displays | head -n 5", mWindowDisplayReceiver));

        String os = String.format("%s(%s) %d",
                device.getProperty(IDevice.PROP_BUILD_VERSION),
                device.getProperty("ro.build.version.preview_sdk"),
                device.getVersion().getApiLevel()); // 8.0(Oreo) 26
        label_os.setText(os);

        // arm64-v8a, armabi-v7a, armeabi
        String abi = device.getProperty(IDevice.PROP_DEVICE_CPU_ABI_LIST);
        label_abilist.setText(abi);

        // ip
        String ip = ShellFacade.INSTANCE.getWlanIpAddr(project, device);
        label_ip_wlan.setText(ip);


    }


    private class WindowDisplayReceiver extends MultiLineReceiver {
        private int densityDpi;
        WindowDisplayReceiver(int densityDpi) {
            this.densityDpi = densityDpi;
        }
        @Override
        public void processNewLines(String[] lines) {
            for (int i = 0; i < lines.length; i++) {
                if (lines[i].contains("init=")) {
                    final String line = lines[i];
                    String[] size = AdbUtil.INSTANCE.getScreenSize(line);
                    Double inch = AdbUtil.INSTANCE.getScreenInch(size, densityDpi);
                    String hdpi = AdbUtil.INSTANCE.getHdpiString(densityDpi);
                    String screen = String.format("%.1f″ %sx%s %s(%d)", inch, size[0], size[1], hdpi, densityDpi); // 5.7 1920*1200 xxhdpi(420)
                    label_screen.setText(screen);
                    break;
                }
            }
        }

        @Override
        public boolean isCancelled() {
            return false;
        }


    }
}
